using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using AuthService.Application.OAuth;
using AuthService.Domain.OAuth;

namespace AuthService.EntityFrameworkCore.OAuth
{
    /// <summary>
    /// OAuth授权仓储实现（简化版）
    /// </summary>
    public class OAuthAuthorizationRepository : EfCoreRepository<AuthServiceDbContext, OAuthAuthorization, Guid>, IOAuthAuthorizationRepository
    {
        public OAuthAuthorizationRepository(IDbContextProvider<AuthServiceDbContext> dbContextProvider)
            : base(dbContextProvider)
        {
        }

        public async Task<OAuthAuthorization> GetByAuthorizationCodeAsync(string authorizationCode, CancellationToken cancellationToken = default)
        {
            return await DbSet
                .FirstOrDefaultAsync(x => x.AuthorizationCode == authorizationCode, GetCancellationToken(cancellationToken));
        }

        public async Task<List<OAuthAuthorization>> GetAuthorizationsByClientIdAsync(Guid clientId, CancellationToken cancellationToken = default)
        {
            return await DbSet
                .Where(x => x.ClientId == clientId)
                .ToListAsync(GetCancellationToken(cancellationToken));
        }

        public async Task<List<OAuthAuthorization>> GetAuthorizationsByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
        {
            return await DbSet
                .Where(x => x.UserId == userId)
                .ToListAsync(GetCancellationToken(cancellationToken));
        }

        public async Task<List<OAuthAuthorization>> GetActiveAuthorizationsAsync(CancellationToken cancellationToken = default)
        {
            return await DbSet
                .Where(x => x.IsActive && !x.IsUsed && x.ExpiresAt > DateTime.Now)
                .ToListAsync(GetCancellationToken(cancellationToken));
        }

        public async Task<List<OAuthAuthorization>> GetExpiredAuthorizationsAsync(CancellationToken cancellationToken = default)
        {
            return await DbSet
                .Where(x => x.ExpiresAt < DateTime.Now)
                .ToListAsync(GetCancellationToken(cancellationToken));
        }

        public async Task<List<OAuthAuthorization>> GetUsedAuthorizationsAsync(CancellationToken cancellationToken = default)
        {
            return await DbSet
                .Where(x => x.IsUsed)
                .ToListAsync(GetCancellationToken(cancellationToken));
        }

        public async Task RevokeAuthorizationsByClientIdAsync(Guid clientId, string reason = "", CancellationToken cancellationToken = default)
        {
            var authorizations = await GetActiveAuthorizationsAsync(cancellationToken);
            var clientAuthorizations = authorizations.Where(x => x.ClientId == clientId);

            foreach (var auth in clientAuthorizations)
            {
                auth.Revoke();
            }
            await SaveChangesAsync(cancellationToken);
        }

        public async Task RevokeAuthorizationsByUserIdAsync(Guid userId, string reason = "", CancellationToken cancellationToken = default)
        {
            var authorizations = await GetActiveAuthorizationsAsync(cancellationToken);
            var userAuthorizations = authorizations.Where(x => x.UserId == userId);

            foreach (var auth in userAuthorizations)
            {
                auth.Revoke();
            }
            await SaveChangesAsync(cancellationToken);
        }

        public async Task<int> CleanupExpiredAuthorizationsAsync(CancellationToken cancellationToken = default)
        {
            var expiredAuthorizations = await GetExpiredAuthorizationsAsync(cancellationToken);
            if (expiredAuthorizations.Any())
            {
                await DeleteManyAsync(expiredAuthorizations, autoSave: true, cancellationToken: cancellationToken);
            }
            return expiredAuthorizations.Count;
        }

        // 简化版实现 - 其他方法根据需要添加
        public async Task<List<OAuthAuthorization>> GetByClientIdAsync(string clientId, CancellationToken cancellationToken = default)
        {
            if (Guid.TryParse(clientId, out var guid))
            {
                return await DbSet
                    .Where(x => x.ClientId == guid)
                    .ToListAsync(GetCancellationToken(cancellationToken));
            }
            return new List<OAuthAuthorization>();
        }

        public async Task<List<OAuthAuthorization>> GetByUserIdAndClientIdAsync(Guid userId, string clientId, CancellationToken cancellationToken = default)
        {
            if (Guid.TryParse(clientId, out var guid))
            {
                return await DbSet
                    .Where(x => x.UserId == userId && x.ClientId == guid)
                    .ToListAsync(GetCancellationToken(cancellationToken));
            }
            return new List<OAuthAuthorization>();
        }

        public async Task<List<OAuthAuthorization>> GetRevokedAuthorizationsAsync(CancellationToken cancellationToken = default)
        {
            return await DbSet
                .Where(x => !x.IsActive)
                .ToListAsync(GetCancellationToken(cancellationToken));
        }

        public async Task RevokeAllAuthorizationsByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
        {
            await RevokeAuthorizationsByUserIdAsync(userId, "", cancellationToken);
        }

        public async Task RevokeAllAuthorizationsByClientIdAsync(string clientId, CancellationToken cancellationToken = default)
        {
            if (Guid.TryParse(clientId, out var guidClientId))
            {
                await RevokeAuthorizationsByClientIdAsync(guidClientId, "", cancellationToken);
            }
        }

        public async Task<OAuthAuthorizationStatisticsDto> GetAuthorizationStatisticsAsync(Guid? userId = null, string clientId = null, CancellationToken cancellationToken = default)
        {
            var query = DbSet.AsQueryable();

            if (userId.HasValue)
                query = query.Where(x => x.UserId == userId.Value);
            if (!string.IsNullOrEmpty(clientId) && Guid.TryParse(clientId, out var guidClientId))
                query = query.Where(x => x.ClientId == guidClientId);

            var authorizations = await query.ToListAsync();

            return new OAuthAuthorizationStatisticsDto
            {
                TotalAuthorizations = authorizations.Count,
                ActiveAuthorizations = authorizations.Count(x => x.IsActive && !x.IsUsed),
                ExpiredAuthorizations = authorizations.Count(x => x.ExpiresAt < DateTime.Now),
                UsedAuthorizations = authorizations.Count(x => x.IsUsed),
                RevokedAuthorizations = authorizations.Count(x => !x.IsActive),
                AuthorizationsByType = authorizations.GroupBy(x => x.AuthorizationType ?? "Unknown").ToDictionary(g => g.Key, g => g.Count()),
                AuthorizationsByClient = authorizations.GroupBy(x => x.ClientId.ToString()).ToDictionary(g => g.Key, g => g.Count())
            };
        }

        public async Task<List<OAuthAuthorization>> GetByUserIdAsync(Guid userId, CancellationToken cancellationToken = default)
        {
            return await GetAuthorizationsByUserIdAsync(userId, cancellationToken);
        }
    }
}